﻿using System;
using System.Collections.Generic;
using Google.GData.Client;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.XPath;
using System.Collections;

namespace LJ2Blogger
{
    class Program
    {
        /** Lists the user's blogs. */
        static void ListUserBlogs(Service service)
        {
            Console.WriteLine("\nRetrieving a list of blogs for your gmail account:");
            FeedQuery query = new FeedQuery();
            // Retrieving a list of blogs
            query.Uri = new Uri("http://www.blogger.com/feeds/default/blogs");
            AtomFeed feed = null;
            feed = service.Query(query);
            foreach (AtomEntry entry in feed.Entries)
            {
                Console.WriteLine("  Blog title: " + entry.Title.Text);
            }
        }

        /** Lists the user's blogs and returns the URI for posting new entries
         * to the blog which the user selected.
         */
        static Uri SelectUserBlog(Service service)
        {

            FeedQuery query = new FeedQuery();
            // Retrieving a list of blogs
            query.Uri = new Uri("http://www.blogger.com/feeds/default/blogs");
            AtomFeed feed = service.Query(query);

            string confirm = "";

            // Publishing a blog post
            Uri blogPostUri = null;
            if (feed != null)
            {
                foreach (AtomEntry entry in feed.Entries)
                {
                    // Print out the title of the Blog
                    Console.WriteLine("  Blog name: " + entry.Title.Text);

                    
                    if (feed.TotalResults == 1)
                    {
                        Console.WriteLine("  Entries will be posted here: " + entry.Title.Text);
                        confirm="y";
                    }
                    else
                    {
                        Console.Write("  Post to this blog? (y/n): ");    
                        confirm = Console.ReadLine();
                    }
                    if (confirm.Equals("y"))
                    {
                        // find the href in the link with a rel pointing to the blog's feed
                        for (int i = 0; i < entry.Links.Count; i++)
                        {
                            if (entry.Links[i].Rel.Equals("http://schemas.google.com/g/2005#post"))
                            {
                                blogPostUri = new Uri(entry.Links[i].HRef.ToString());
                                Console.WriteLine("  Your new posts will be sent to " + blogPostUri.AbsoluteUri.ToString());
                            }
                        }
                        return blogPostUri;
                    }
                }
            }
            return blogPostUri;
        }

        /** Display the titles for all entries in the previously selected blog. */
        static void ListBlogEntries(Service service, Uri blogUri)
        {
            if (blogUri != null)
            {
                Console.WriteLine("\nRetrieving all blog posts");
                // Retrieve all posts in a blog
                FeedQuery query = new FeedQuery();
                Console.WriteLine("  Query URI: " + blogUri.ToString());
                query.Uri = blogUri;
                AtomFeed feed = service.Query(query);
                foreach (AtomEntry entry in feed.Entries)
                {
                    Console.WriteLine("  Entry Title: " + entry.Title.Text);
                }
            }
        }

        static bool CheckEntryExists(Service service, Uri blogUri, DateTime EntryDateTime, string EntryTitle)
        {
            bool result = false;
            FeedQuery query = new FeedQuery();
            query.Uri = blogUri;
                        query.MinPublication = new DateTime(EntryDateTime.Year, EntryDateTime.Month,EntryDateTime.Day);
            query.MaxPublication = new DateTime(EntryDateTime.Year, EntryDateTime.Month, EntryDateTime.Day).AddDays(1);
            AtomFeed feed = service.Query(query);


            foreach (AtomEntry entry in feed.Entries) {
                if (entry.Published.Date.Equals(EntryDateTime.Date) && 
                    entry.Published.Hour.Equals(EntryDateTime.Hour) &&
                    entry.Published.Minute.Equals(EntryDateTime.Minute) &&
                    entry.Published.Second.Equals(EntryDateTime.Second))
                {                    
                    if (entry.Title.Text.Equals(EntryTitle))
                    {
                        Console.WriteLine("Found duplicate entry: '" + entry.Title.Text + "' dated" + entry.Published.ToString());
                        Console.WriteLine("vs " + EntryTitle);
                        result = true;
                    } 
                }
            }

            return result;
        }

        /** Display title for entries in the blog in the hard coded date range. */
        static void ListBlogEntriesInDateRange(Service service, Uri blogUri)
        {
            Console.WriteLine("\nRetrieving posts using query parameters");
            // Retrieve all posts in a blog between Jan 1, 2006 and Apr 12, 2007
            FeedQuery query = new FeedQuery();
            query.Uri = blogUri;
            query.MinPublication = new DateTime(2006, 1, 1);
            query.MaxPublication = new DateTime(2007, 4, 12);
            AtomFeed feed = service.Query(query);
            foreach (AtomEntry entry in feed.Entries)
            {
                Console.WriteLine("  Entry Title: " + entry.Title.Text);
            }
        }

        /** Change the contents of the newly created blog entry. */
        static AtomEntry EditEntry(AtomEntry toEdit)
        {
            Console.WriteLine("\nUpdating post");
            // Edit the new entry
            if (toEdit != null)
            {
                toEdit.Title.Text = "Marriage Woes!";
                Console.WriteLine("  Press enter to update");
                Console.ReadLine();
                toEdit = toEdit.Update();
            }
            return toEdit;
        }

        /** Delete the specified blog entry. */
        static void DeleteEntry(AtomEntry toDelete)
        {
            Console.WriteLine("\nDeleting post");
            // Delete the edited entry
            if (toDelete != null)
            {
                Console.WriteLine("  Press enter to delete the new blog post");
                Console.ReadLine();
                toDelete.Delete();
            }
        }

        /** Get the comments feed URI for the desired blog entry. */
        static Uri SelectBlogEntry(Service service, Uri blogPostUri)
        {
            Console.WriteLine("\nPlease select a blog entry on which to comment.");
            FeedQuery query = new FeedQuery();
            query.Uri = blogPostUri;
            AtomFeed feed = service.Query(query);
            Uri commentPostUri = null;

            if (feed != null)
            {
                foreach (AtomEntry entry in feed.Entries)
                {
                    // Print out the title of the Blog
                    Console.WriteLine("  Blog entry title: " + entry.Title.Text);
                    Console.Write("  Post a comment on this entry? (y/n): ");

                    if (Console.ReadLine().Equals("y"))
                    {
                        // Create the Post URL for adding a comment by finding this entry's id number.

                        // Find the href in the link with a rel pointing to the blog's feed.
                        for (int i = 0; i < entry.Links.Count; i++)
                        {
                            
                            if (entry.Links[i].Rel == "edit")
                            {
                                string commentUriStart = Regex.Replace(blogPostUri.ToString(), "/posts/default", "");
                                string selfLink = entry.Links[i].HRef.ToString();
                                string entryId = Regex.Replace(selfLink, blogPostUri.ToString() + "/", "");
                                // Build the comment URI from the blog id in and the entry id.
                                commentPostUri = new Uri(commentUriStart + "/" + entryId + "/comments/default");
                                Console.WriteLine("  Your new comments will be sent to " + commentPostUri.ToString());
                                return commentPostUri;
                            }
                        }
                    }
                }
            }

            return commentPostUri;
        }

        static AtomEntry PostNewComment(Service service, Uri commentPostUri)
        {
            Console.WriteLine("\nCommenting on a blog post");
            AtomEntry postedComment = null;
            if (commentPostUri != null)
            {
                // Add a comment.
                AtomEntry comment;
                comment = new AtomEntry();
                comment.Title.Text = "This is my first comment";
                comment.Content.Content = "This is my first comment";
                comment.Authors.Add(new AtomPerson());
                comment.Authors[0].Name = "Blog Author Name";
                postedComment = service.Insert(commentPostUri, comment);
                Console.WriteLine("  Result's title: " + postedComment.Title.Text);
            }
            return postedComment;
        }

        static void ListEntryComments(Service service, Uri commentUri)
        {
            if (commentUri != null)
            {
                Console.WriteLine("\nRetrieving all blog post comments");
                // Retrieve all comments on a blog entry
                FeedQuery query = new FeedQuery();
                Console.WriteLine("  Query URI: " + commentUri.ToString());
                query.Uri = commentUri;
                AtomFeed feed = service.Query(query);
                foreach (AtomEntry entry in feed.Entries)
                {
                    Console.WriteLine("  Comment Title: " + entry.Title.Text);
                }
            }
        }

        static void DeleteComment(AtomEntry commentEntry)
        {
            Console.WriteLine("\nDeleting the comment");
            if (commentEntry != null)
            {
                // Delete the comment.
                Console.WriteLine("  Press enter to delete the new comment post");
                Console.ReadLine();
                commentEntry.Delete();
            }
        }

        static void Main(string[] args)
        {
            Service service = new Service("blogger", "Slavko's LJ import tool");

            // ClientLogin using username/password authentication
            string username;
            string password;
            string ljfile;

            if (args.Length != 3)
            {
                Console.WriteLine("Usage: LJ2Blogger.exe <username> <password> <exported lj file>");
                return;
            }
            else
            {
                username = args[0];
                password = args[1];
                ljfile = args[2];
            }

            service.Credentials = new GDataCredentials(username, password);

            ListUserBlogs(service);
            Uri blogPostUri = SelectUserBlog(service);

            RepostLJXMLToBlogger(service, blogPostUri, ljfile);

            //AtomEntry createdEntry = PostNewEntry(service, blogPostUri);
            //PostAndDeleteNewDraftEntry(service, blogPostUri);
            //ListBlogEntries(service, blogPostUri);
            //ListBlogEntriesInDateRange(service, blogPostUri);
            //AtomEntry editedEntry = EditEntry(createdEntry);
            //DeleteEntry(editedEntry);
            //Uri commentPostUri = SelectBlogEntry(service, blogPostUri);
            //AtomEntry commentEntry = PostNewComment(service, commentPostUri);
            //ListEntryComments(service, commentPostUri);
            //DeleteComment(commentEntry);

            Console.WriteLine("All done");

        }

        private static void RepostLJXMLToBlogger(Service service, Uri blogPostUri, string FileName)
        {

            XmlDocument LJFile = new XmlDocument();
            LJFile.Load(FileName);

            XmlNodeList Entries = LJFile.SelectNodes("livejournal/entry");

            IEnumerator EntriesIterator = Entries.GetEnumerator();
            
            while (EntriesIterator.MoveNext()) {
                XmlElement Entry = (XmlElement)EntriesIterator.Current;
                string entryid = Entry.SelectSingleNode("itemid/text()").Value;
                string entrysubject = "";
                if (Entry.SelectSingleNode("subject/text()") != null)
                {
                    entrysubject = Entry.SelectSingleNode("subject/text()").Value;
                }
                DateTime entrydate = DateTime.Parse(Entry.SelectSingleNode("eventtime/text()").Value);
                string entrycontent = Entry.SelectSingleNode("event").InnerXml;
                string entryallowmask = Entry.SelectSingleNode("allowmask/text()").Value;

                if (CheckEntryExists(service, blogPostUri, entrydate, entrysubject) == false)
                {

                    Console.WriteLine("\nPublishing a blog for LJ entry {0}", entryid);
                    AtomEntry createdEntry = null;
                    if (blogPostUri != null)
                    {
                        // construct the new entry
                        AtomEntry newPost = new AtomEntry();
                        newPost.Title.Text = entrysubject;
                        newPost.Content = new AtomContent();
                        newPost.Content.Content = entrycontent;
                        newPost.Updated = entrydate;
                        newPost.Published = entrydate;


                        newPost.Content.Type = "text";

                        //newPost.Authors.Add(new AtomPerson());
                        //newPost.Authors[0].Name = "Elizabeth Bennet";
                        //newPost.Authors[0].Email = "liz@gmail.com";

                        if (entryallowmask.Equals("0"))
                        {
                            createdEntry = service.Insert(blogPostUri, newPost);

                            if (createdEntry != null)
                            {
                                if ((CheckEntryExists(service, blogPostUri, entrydate,entrysubject) == true))
                                {
                                    Console.WriteLine("  New blog post created with title: " + createdEntry.Title.Text);
                                }
                                else
                                {
                                    Console.WriteLine("Entry was not actually published. Rate exceeded. Please wait 24h");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Post failure");
                            }
                        }
                    }


                    Console.WriteLine(".");
                }
                else
                {
                    Console.WriteLine ("Entry already exists, skipping");
                }
            }           


        }
    }

}
